﻿#pragma once
#include "Parser.h"
#include "Logging.h"
#include <any>
#include <map>
#include <type_traits>

class AnyParser : public Parser
{
public:
  bool HaveVariable(const std::string& name) const { return _container.count(name) > 0; }

  template<typename T, typename std::enable_if<!is_vector<T>::value>::type* = nullptr>
  T Get(const std::string& name) const
  {
    if (!HaveVariable(name))
    {
      console::Error(name, "不存在");
    }

    try
    {
      return std::any_cast<T>(_container.at(name));
    }
    catch (const std::exception& e)
    {
      console::Error(e.what());
    }
  }

  template<typename T>
  T Get(const std::string& name, T&& default) const
  {
    if (!HaveVariable(name))
    {
      return default;
    }

    try
    {
      return std::any_cast<T>(_container.at(name));
    }
    catch (const std::exception& e)
    {
      console::Error(e.what());
    }
  }
  template<typename T, typename std::enable_if<is_vector<T>::value>::type* = nullptr>
  T Get(const std::string& name, bool required = false) const
  {
    if (!HaveVariable(name) && required)
    {
      console::Error(name, "不存在");
    }

    try
    {
      return std::any_cast<T>(_container.at(name));
    }
    catch (const std::exception& e)
    {
      return T{};
    }
  }

  template<typename T>
  void Set(const std::string& name, const T& value)
  {
    if (HaveVariable(name))
    {
      console::Error(name, "已经存在");
    }
    _container[name] = value;
  }

private:
  using Container = std::map<std::string, std::any>;
  Container _container; // 接受Add
};
